class Marcacion < ActiveRecord::Base
  TManual=0#creadas a travez del marcardor
  TAgregada=1#creadas  al arreglar las marcaciones
  TGrupal=2#creadas en grupos
  
  belongs_to :importacion
  belongs_to :usuario
  belongs_to :responsable,:class_name=>"Usuario"
  validates_presence_of :usuario,:fecha
  default_scope :conditions=>{:deleted_at=>nil},:order=>"fecha, hora" 
  named_scope :por_mes, lambda{|fecha| {:conditions => ["fecha between ? and ?",fecha.beginning_of_month,fecha.end_of_month]}}
  named_scope :por_periodo, lambda{|inicio,fin| {:conditions => ["fecha between ? and ?",inicio,fin]}}
  named_scope :por_fecha, lambda{|fecha| {:conditions => ["fecha between ? and ?",fecha,fecha] }}
  named_scope :manuales, :conditions => {:tipo=>TManual}
  #TODO Usar logica del metodo self.irregualares para generar el reporte.
  #TODO Mejorar como se muestran los planes de horarios.
  def self.generar_ficha_pdf(fecha_solicitada,usuarios,current_user)
    Prawn::Document.new(:page_size=> [1008.00,612.00],:page_layout => :landscape,
      :top_margin => 5,:right_margin => 5) do |pdf|
      usuarios.each do |usuario|
        pdf.define_grid(:columns=>10,:rows=>20,:gutter=>0)
        pdf.grid([0,0],[0,19]).bounding_box() do
          pdf.text "Fecha: #{I18n.l(Time.now,:format=>:date)}",:size=>8
          pdf.text "Hora: #{I18n.l(Time.now,:format=>:time)}",:size=>8
          pdf.text "Usuario: #{current_user.nombre}",:size=>8
        end
        pdf.grid([1,0],[1,9]).bounding_box do
          pdf.text "BitacorH",:size=>25,:align=>:center,:style=>:bold,:valign => :top
          pdf.text "Tarjeta de Marcación", :size=>15, :align=>:center,:valign => :bottom
        end
        pdf.grid([2,0],[6,9]).bounding_box do
          pdf.text    "<b>Nro. Funcionario:</b><a href='#{APP_CONFIG[:site_url]}/usuarios/#{usuario.id}'>#{usuario.codigo}</a>", :size=>10,    :inline_format => true
          pdf.text    "<b>Nombre:</b> #{usuario.nombres}", :size=>10,             :inline_format => true
          pdf.text    "<b>Cargo:</b> #{usuario.cargo.try(:nombre)}", :size=>10,         :inline_format => true
          pdf.text    "<b>Horarios:</b>",    :inline_format => true, :size=>10

          usuario.planes_horarios.por_mes(fecha_solicitada).each do |ph|
            unless ph.inicio.blank?
              pdf.text "<b>Del:</b> #{I18n.l(ph.inicio).to_s} <b>Al:</b>  #{ph.fin ? I18n.l(ph.fin).to_s : '(no especificado)'}" ,:inline_format => true, :size=>10,:indent_paragraphs => 40
              pdf.text "<b>Carga:</b>  #{ph.grupo_horario.carga.to_s}"                                   ,:inline_format => true, :size=>10,:indent_paragraphs => 40
              pdf.text "<b>Controla Salida:</b>  #{ph.grupo_horario.controla_salida?}"                                   ,:inline_format => true, :size=>10,:indent_paragraphs => 40
              ph.grupo_horario.resumen_horarios.each do |r|
                pdf.text r,:inline_format => true, :size=>10,:indent_paragraphs => 60
              end
            end
          end
        end


        #procesamiento de datos
        usuario.planes_horarios.por_mes(fecha_solicitada).blank? ? inicio_marcaciones=4 : inicio_marcaciones=7
        pdf.grid([inicio_marcaciones,0],[19,9]).bounding_box do
          total_ht=0
          marcaciones  =  [["","#{I18n.l(fecha_solicitada,:format=>:full_month_name)} - #{fecha_solicitada.year}",""],["Dia","Marcaciones","Horas Trabajadas"]]
          marcaciones_texto = ' (no marco) '
          horas_trabajadas=0
          dias_no_marcados=0
          feriado=false
          domingo=false
          fecha_solicitada.beginning_of_month.upto(fecha_solicitada.end_of_month) do |date|
            feriado=!Feriado.find_by_fecha(date.day,date.month).blank?
            domingo=(date.cwday==7)

            unless usuario.marcaciones.por_fecha(date).blank?
              dm=DiaMarcacion.new(usuario,date)
              total_ht+=dm.horas_trabajadas
              marcaciones_texto=dm.marcaciones_texto + (dm.incompleta? ? " (incompleta)":"")
              horas_trabajadas=dm.horas_trabajadas
            else
              horas_trabajadas=0
              marcaciones_texto = (domingo || feriado) ? '' : ' (no marco) '
              marcaciones_texto += domingo ? '(Domingo) ' : ''
              marcaciones_texto += feriado ? '(Feriado) ' : ''
            end
            marcaciones <<["#{I18n.l(date,:format=>:abbr_day_names)} - #{date.day}",marcaciones_texto,horas_trabajadas]

            dias_no_marcados+=1 if (!feriado and !domingo and horas_trabajadas==0)
          end
          marcaciones <<['','Cantidad de dias no marcados:  '+dias_no_marcados.to_s,'Total: '+total_ht.to_s]

          pdf.table(marcaciones,:header=>true,:column_widths => {1 => 450},:cell_style => { :inline_format => true }) do |t|
            t.cells.size = 8
            t.cells.padding=2
            t.row(0).borders = []
            t.row(0).font_style = :bold
            t.row(0).size = 10
            t.row(0).align = :center
            t.row(1).font_style = :bold
            t.row(1).align = :center
            t.row(1).size = 10
            t.row(t.row_length-1).borders = []
            t.row(t.row_length-1).font_style = :bold
            t.cells[t.row_length-1,2].borders = [:left, :right,:bottom]
          end
        end

        unless usuario == usuarios.last
          pdf.start_new_page
        end

      end #usuarios.each
    end.render
  end

  def horaf
    self.hora.strftime("%H:%M")
  end

  def self.irregulares(fecha,funcionarios)
    irregulares=[]
    ids_funcionarios=funcionarios.map(&:id)
    marcaciones=get_grouped_marcaciones(fecha,ids_funcionarios)
    tolerancia_tardias=Parametro.find_by_codigo('PV01').try(:valor).to_i
    ids_plan_accion,planes_horarios=get_grouped_planes_horarios(fecha,ids_funcionarios)
    grupos_horarios=get_grouped_grupos_horarios(ids_plan_accion)    
    autorizaciones=Autorizacion.por_mes(fecha).find(:all,:conditions=>{:usuario_id=>ids_funcionarios}).group_by(&:fecha)
    
    fecha.beginning_of_month.upto(fecha.end_of_month) do |date|
      next if marcaciones[date].blank?
      funcionarios.each do |funcionario|
        marcaciones[date][funcionario.id].blank? ? next : marcaciones_x_funcionario_x_dia=marcaciones[date][funcionario.id]
        plan_horario=planes_horarios.select{|k,v| k.include?(date)}.first.try(:second)
        next if plan_horario.blank?
        dm=DiaMarcacion.new(funcionario,date,
          :marcaciones=>marcaciones_x_funcionario_x_dia,
          :plan_horario=>plan_horario,
          :autorizaciones=>autorizaciones,
          :tolerancia_tardias=>tolerancia_tardias,
          :grupo_horario=>grupos_horarios[plan_horario.grupo_horario_id].first)
        irregulares<<dm if dm.irregular?(true)
      end
    end
    irregulares
  end
  
  private
  
  def self.get_grouped_marcaciones(fecha,ids_funcionarios)
    marcaciones=Marcacion.por_periodo(fecha,fecha.end_of_month).find(:all,:conditions=>{:usuario_id=>ids_funcionarios})
    marcaciones=marcaciones.group_by(&:fecha)
    marcaciones.each{|k,v| marcaciones[k]=marcaciones[k].group_by(&:usuario_id)}
    marcaciones
  end
  
  def self.get_grouped_planes_horarios(fecha,ids_funcionarios)
    datos=PlanHorario.por_mes(fecha).find(:all,:conditions=>{:usuario_id=>ids_funcionarios})
    ids_grupo_horario=datos.map(&:grupo_horario_id).uniq
    planes_horarios={}
    datos.map{|ph,fin,inicio| 
      fin=ph.fin ? ph.fin : Date.today 
      inicio=ph.inicio ? ph.inicio : Date.today 
      planes_horarios.merge!({(inicio..fin)=>ph})}
    [ids_grupo_horario,planes_horarios]
  end
  
  def self.get_grouped_grupos_horarios(ids)
    GrupoHorario.find(:all,:conditions=>{:id=>ids}).group_by(&:id)
  end
end

